昨天我們已經學會如何建立一個 gem,今天就直接開始進入主題吧!
Rack 是一個應用程式能讓你的框架與 server 進行溝通,可以說是大部分用 ruby 開發的 framework,都是以他為基礎,所以也會有人稱呼 Rails 其實就是一個 Rack app,關於 Rack 的官方說明如下
Rack is a gem to interface your framework to a Ruby application server such as Mongrel, Thin, Lighttpd, Passenger, WEBrick or Unicorn. An application server is a special type of web server that runs server applications, often in Ruby. In a real production environment you would run a web server like Apache or NGinX in front of the application servers.
看說明其實不是那麼好懂(其實是英文不好),只知道他介於 web framework(例如: Rails) 和 web server(例如: Nginx)之間,搭配圖片說明可能比較清楚 Rack 在幹嘛
看完圖片後,對於現在的我們來說,只要先記住兩件事情就好
一樣跟昨天一天,認識一個新的東西,先從基本的範例開始學起,我們先建立一個 my_rack
的目錄,並且在底下建立一個 config.ru
檔案
# my_rack/config.ru
run proc {
[200, {'Content-Type' => 'text/html'},
["Hola, El mundo!"]]
}
這段程式碼表示當瀏覽器每次執行 request
時,Rack 就會執行 run proc {}
,並且 response
會回傳一個 http status code
為 200, 同時也會告訴瀏覽器 HTTP header 和 body
接著開啟 web server rackup -p 3001
$ rackup -p 3001
Puma starting in single mode...
* Version 4.3.5 (ruby 2.6.6-p146), codename: Mysterious Traveller
* Min threads: 0, max threads: 16
* Environment: development
* Listening on tcp://127.0.0.1:3001
* Listening on tcp://[::1]:3001
打開瀏覽器,連到 http://127.0.0.1:3001/
,這時候就會在瀏覽器上看到以下文字
Hola, El mundo!
現在我們已經知道怎麼做出一個 gem,也知道 Rails 是基於 Rack 建立的 web framework 接下來就正式開始來建立一個 framework,吧!
$ mavericks/bundle gem mavericks
框架的名字看自己的喜好而定,但如果要上傳到 rubygems.org
,記得先檢查名字是不是被人用過,這裡我替這個框架命名為 Mavericks
接著跟之前一樣,把 gemspec 裡面的 TODO
都先填寫完,然後在 gemspec 的最底下加上
# mavericks/mavericks.gemspec
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
# 加上底下這行
spec.add_runtime_dependency "rack"
代表 Mavericks
這個框架會用到 Rack,如果你想加上測試工具(ex: Rspec),也可以加上
gem.add_development_dependency "rspec"
接著執行 build,然後將 gem 安裝在電腦上
gem build mavericks.gemspec
gem install mavericks-0.1.0.gem
在第一天的時候有提到,我們會用我們所建立的框架,來做一個 Todo list 的網站,今天就順手一起建立吧!當然現在還沒辦法像 Rails 一樣,執行 rails new app_name
就很快生成專案,所以現在辛苦一點,先徒手建立,這裡我們把專案名稱取名為 just_do
,做就對了
$ mkdir just_do
$ cd just_do
# 建立 config 和 app 資料夾
$ mkdir config
$ mkdir app
# 建立 Gemfile
$ touch Gemfile
在 Gemfile 裡面加上你剛剛建立好的 Mavericks
# just_do/Gemfile
source 'https://rubygems.org'
gem 'mavericks'
然後就跟 Rails 一樣,加上 gem 以後記得先 bundle,bundle 完就會生成出 Gemfile.lock
檔案
$ bundle install
接著繼續在專案目錄底下建立 config.ru,填上 response 的內容
# just_do/config.ru
run proc {
[200, {'Content-Type' => 'text/html'},
["Just do !!"]]
}
最後啟動 server
$ rackup -p 3001
打開瀏覽器連到 http://127.0.0.1:3001/
,沒意外的話應該會在畫面上看到這串文字
Just do !!
雖然可以正常運作,但現在的狀況有點像是,由 just_do 這個專案在處理 request
,我們應該要讓 Mavericks 來處理才對(不然安裝他幹嘛),所以要稍微修改一下程式碼,讓我們再回到 Mavericks
# mavericks/lib/mavericks.rb
require "mavericks/version"
module Mavericks
class Error < StandardError; end
class Application
def call(env)
[200, {'Content-Type' => 'text/html'},
["I use mavericks, just do !!"]]
end
end
end
然後一樣重新 build 新的 gem 並且安裝
gem build mavericks.gemspec
gem install mavericks-0.1.0.gem
注意要把舊的
mavericks-0.1.0.gem
,並且執行git add
.,不然在 build 的過程中會出錯
接著再回到 just_do 的專案,建立一個 config/application.rb
檔案
# just_do/config/application.rb
require 'mavericks'
module JustDo
class Application < Mavericks::Application
end
end
將 Mavericks require 進來以後,讓 class Applicaion
做繼承,最後修改 config.ru 這個檔案,把原本的程式碼換成底下這段
# just_do/config.ru
require_relative 'config/application'
run JustDo::Application.new
這裡利用 Rack 的 run
來執行 Application 的物件,只要這個物件帶有 call
這個 method,Rack 就會去執行裡面那段程式碼,接下來跟剛剛一樣啟動伺服器查看瀏覽器畫面
I use mavericks, just do !!
如果你現在建立一個 Rails 專案,你會發現 Rails 也是在做一樣的事情
# ./config/application.rb
module Cart
class Application < Rails::Application
(略)
end
end
# ./config.ru
require_relative 'config/environment'
run Rails.application
比較我們的 Mavericks 和 Rails 的專案,同樣的都繼承了 Application,接著在 config.ru 執行一個 Rack Application,到這裡有沒有開始覺得,好像有這麼一點,我們真的在做框架的感覺?
讀者:「X啦,我們根本沒辦法建立自己的內容呀,這是什麼網頁框架」(按檢舉)
先...先等等...,才第三天而已
現在我們運用這兩天學到的知識,建立起一個簡單的 framework 名叫 Mavericks,Mavericks 裡面用了 Rack 來幫助我們接收 request,也可以做出基本回應,但很明顯的我們還缺少很多東西,尤其是整個 MVC 的架構,明天我們將會從 controller 開始建立